home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_054 / ispell / ispell.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  13KB  |  707 lines

  1. /* -*- Mode:Text -*- */
  2. /*
  3.  * ispell.c - An interactive spelling corrector.
  4.  *
  5.  * Copyright (c), 1983, by Pace Willisson
  6.  * Permission for non-profit use is hereby granted.
  7.  * All other rights reserved.
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include "ispell.h"
  13.  
  14. #define NOPARITY 0x7f 
  15.  
  16. FILE *infile;
  17. FILE *outfile;
  18.  
  19. char rootword[BUFSIZ];
  20.  
  21. givehelp ()
  22. {
  23.     erase ();
  24.     printf ("Whenever a word is found that is not in the dictionary,\r\n");
  25.     printf ("it is printed on the first line of the screen.  If the dictionary\r\n");
  26.     printf ("contains any similar words, they are listed with a single digit\r\n");
  27.     printf ("next to each one.  You have the option of replacing the word\r\n");
  28.     printf ("completely, or choosing one of the suggested words.\r\n");
  29.     printf ("\r\n");
  30.     printf ("Commands are:\r\n\r\n");
  31.     printf ("R       Replace the misspelled word completely.\r\n");
  32.     printf ("Space   Accept the word this time only\r\n");
  33.     printf ("A       Accept the word for the rest of this file.\r\n");
  34.     printf ("I       Accept the word, and put it in your private dictionary.\r\n");
  35.     printf ("0-9     Replace with one of the suggested words.\r\n");
  36.     printf ("Q       Write the rest of this file, ignoring misspellings, ");
  37.     printf (         "and start next file.\r\n");
  38.     printf ("X       Exit immediately.  Asks for conformation.  ");
  39.     printf (         "Leaves file unchanged.\r\n");
  40.     printf ("!       Shell escape.\r\n");
  41.     printf ("^L      Redraw screen.\r\n");
  42.     printf ("\r\n\r\n");
  43.     printf ("-- Type space to continue --");
  44.     fflush (stdout);
  45.     getchar ();
  46. }
  47.  
  48.  
  49. char *getline();
  50.  
  51. int lflag = 0;
  52. int aflag = 0;
  53. int fflag = 0;
  54. int sflag = 0;
  55.  
  56. char *askfilename;
  57.  
  58. usage ()
  59. {
  60.     fprintf (stderr, "Usage: spell [ file ... | -a | -l | -f file | -s ]\n");
  61.     exit (1);
  62. }
  63.  
  64. main (argc, argv)
  65. char **argv;
  66. {
  67.     argv++;
  68.     argc--;
  69.     while (argc && **argv == '-') {
  70.         switch ((*argv)[1]) {
  71.         case 'a':
  72.             aflag++;
  73.             break;
  74.         case 'f':
  75.             fflag++;
  76.             argv++; argc--;
  77.             if (argc == 0)
  78.                 usage ();
  79.             askfilename = *argv;
  80.             break;
  81.         case 'l':
  82.             lflag++;
  83.             break;
  84.         case 's':
  85.             sflag++;
  86.             break;
  87.         }
  88.         argv++; argc--;
  89.     }
  90.  
  91.     if (!argc && !lflag && !aflag)
  92.         usage ();
  93.  
  94.     if (linit () < 0)
  95.         exit (0);
  96.  
  97.     treeinit ();
  98.  
  99.     if (aflag) {
  100.         askmode ();
  101.         exit (0);
  102.     }
  103.  
  104.     if (lflag) {
  105.         infile = stdin;
  106.         checkfile ();
  107.         exit (0);
  108.     }
  109.  
  110.     terminit ();
  111.  
  112.     while (argc--)
  113.         dofile (*argv++);
  114.  
  115.     done ();
  116. }
  117.  
  118. char firstbuf[BUFSIZ], secondbuf[BUFSIZ];
  119. char *currentchar;
  120. char token[BUFSIZ];
  121.  
  122. int quit;
  123.  
  124. char *currentfile = NULL;
  125.  
  126. dofile (filename)
  127. char *filename;
  128. {
  129.     int c;
  130.     char    bakfile[256];
  131.  
  132.     currentfile = filename;
  133.  
  134.     if ((infile = fopen (filename, "r")) == NULL) {
  135.         fprintf (stderr, "Can't open %s\r\n", filename);
  136.         sleep (2);
  137.         return;
  138.     }
  139.  
  140.     if (access (filename, 2) < 0) {
  141.         fprintf (stderr, "Can't write to %s\r\n", filename);
  142.         sleep (2);
  143.         return;
  144.     }
  145.  
  146. #ifdef unx
  147.     strcpy (tempfile, "/usr/tmp/spellXXXXXX");
  148.     mktemp (tempfile);
  149. #else
  150.     strcpy (tempfile, "t:ISpelltemp");  /* Needs fix to make uniq!! (fnf) */
  151. #endif
  152.     if ((outfile = fopen (tempfile, "w")) == NULL) {
  153.         fprintf (stderr, "Can't create %s\r\n", tempfile);
  154.         sleep (2);
  155.         return;
  156.     }
  157.  
  158.     quit = 0;
  159.  
  160.     checkfile ();
  161.  
  162.     fclose (infile);
  163.     fclose (outfile);
  164.  
  165.     treeoutput ();
  166.  
  167.     if ((infile = fopen (tempfile, "r")) == NULL) {
  168.         fprintf (stderr, "tempoary file disappeared (%s)\r\n", tempfile);    
  169.         sleep (2);
  170.         return;
  171.     }
  172.  
  173.     sprintf(bakfile, "%s.bak", filename);
  174.  
  175. #ifdef unix
  176.     if(link(filename, bakfile) == 0)
  177.         unlink(filename);
  178. #else
  179.     if(rename(filename, bakfile) == -1) {
  180.         fprintf (stderr, "sorry, can't rename %s as %s\n",
  181.             filename, bakfile);
  182.         sleep (2);
  183.         return;
  184.     }
  185. #endif
  186.  
  187.     if ((outfile = fopen (filename, "w")) == NULL) {
  188.         fprintf (stderr, "can't create %s\r\n", filename);
  189.         sleep (2);
  190.         return;
  191.     }
  192.  
  193.     while ((c = getc (infile)) != EOF)
  194.         putc (c, outfile);
  195.  
  196.     fclose (infile);
  197.     fclose (outfile);
  198.  
  199.     unlink (tempfile);
  200. }
  201.  
  202. checkfile ()
  203. {
  204.     int c;
  205.     char *p;
  206.     int len;
  207.  
  208.     secondbuf[0] = 0;
  209.     currentchar = secondbuf;
  210.  
  211.     while (1) {
  212.         strcpy (firstbuf, secondbuf);
  213.         if (quit) {    /* quit can't be set in l mode */
  214.             while (fgets (secondbuf, sizeof secondbuf, infile) != NULL)
  215.                 fputs (secondbuf, outfile);
  216.             break;
  217.         }
  218.  
  219.         if (fgets (secondbuf, sizeof secondbuf, infile) == NULL)
  220.             break;
  221.         currentchar = secondbuf;
  222.         
  223.         len = strlen (secondbuf) - 1;
  224.         if (secondbuf [ len ] == '\n')
  225.             secondbuf [ len ] = 0;
  226.  
  227.         /* if this is a formatter command, skip over it */
  228.         if (*currentchar == '.') {
  229.             while (*currentchar && !isspace (*currentchar)) {
  230.                 if (!lflag)
  231.                     putc (*currentchar, outfile);
  232.                 currentchar++;
  233.             }
  234.             if (*currentchar == 0) {
  235.                 putc ('\n', outfile);
  236.                 continue;
  237.             }
  238.         }
  239.  
  240.         while (1) {
  241.             while (*currentchar && !isalpha (*currentchar)) {
  242.                 /* formatting escape sequences */
  243.                 if (*currentchar == '\\') {
  244.                     if(currentchar[1] == 'f') {
  245.                     /* font change: \fX */
  246.                     copyout(¤tchar, 3);
  247.                     continue;
  248.                     }
  249.                     else if(currentchar[1] == 's') {
  250.                     /* size change */
  251.                     if(currentchar[2] < 6 &&
  252.                        currentchar[2] != 0)
  253.                         /* two digit size */
  254.                         copyout(¤tchar, 4);
  255.                     else
  256.                         /* one digit size */
  257.                         copyout(¤tchar, 3);
  258.                     continue;
  259.                     }
  260.                     else if(currentchar[1] == '(') {
  261.                     /* extended char set escape: \(XX */
  262.                     copyout(¤tchar, 4);
  263.                     continue;
  264.                     }
  265.                 }
  266.  
  267.                 if (!lflag)
  268.                     putc (*currentchar, outfile);
  269.                 currentchar++;
  270.             }
  271.  
  272.             if (*currentchar == 0)
  273.                 break;
  274.  
  275.             p = token;
  276.             while (isalpha (*currentchar) ||
  277.                    (*currentchar == '\'' &&
  278.                 (isalpha (*(currentchar + 1)))))
  279.               *p++ = *currentchar++;
  280.             *p = 0;
  281.             if (lflag) {
  282.                 if (!good (token))
  283.                     printf ("%s\r\n", token);
  284.             } else {
  285.                 if (!quit)
  286.                 correct (token, ¤tchar);
  287.             }
  288.             if (!lflag)
  289.                 fprintf (outfile, "%s", token);
  290.         }
  291.         putc ('\n', outfile);
  292.     }
  293. }
  294.  
  295. char possibilities[10][BUFSIZ];
  296. int pcount;
  297.  
  298. correct (token, currentchar)
  299. char *token;
  300. char **currentchar;
  301. {
  302.     int c;
  303.     int i;
  304.     char *p;
  305.     int len;
  306.     char *begintoken;
  307.  
  308.     len = strlen (token);
  309.     begintoken = *currentchar - len;
  310.  
  311. checkagain:
  312.     if (good (token))
  313.         return;
  314.  
  315.     erase ();
  316.     printf ("    %s", token);
  317.     if (currentfile)
  318.         printf ("              File: %s", currentfile);
  319.     printf ("\r\n\r\n");
  320.  
  321.     makepossibilities (token);
  322.  
  323.     for (i = 0; i < 10; i++) {
  324.         if (possibilities[i][0] == 0)
  325.             break;
  326.         printf ("%d: %s\r\n", i, possibilities[i]);
  327.     }
  328.  
  329.     move (15, 0);
  330.     printf ("%s\r\n", firstbuf);
  331.  
  332.     for (p = secondbuf; p != begintoken; p++)
  333.         putchar (*p);
  334.     inverse ();
  335.     for (i = strlen (token); i > 0; i--)
  336.         putchar (*p++);
  337.     normal ();
  338.     while (*p)
  339.         putchar (*p++);
  340.     printf ("\r\n");
  341.  
  342.     while (1) {
  343.         switch (c = (getchar () & NOPARITY)) {
  344.         case 'Z' & 037:
  345.             stop ();
  346.             erase ();
  347.             goto checkagain;
  348.         case ' ':
  349.             erase ();
  350.             return;
  351.         case 'x': case 'X':
  352.             printf ("Are you sure you want to throw away your changes? ");
  353.             c = (getchar () & NOPARITY);
  354.             if (c == 'y' || c == 'Y') {
  355.                 erase ();
  356.                 done ();
  357.             }
  358.             putchar (7);
  359.             goto checkagain;
  360.         case 'i': case 'I':
  361.             treeinsert (token, 1);
  362.             erase ();
  363.             return;
  364.         case 'a': case 'A':
  365.             treeinsert (token, 0);
  366.             erase ();
  367.             return;
  368.         case 'L' & 037:
  369.             goto checkagain;
  370.         case '?':
  371.             givehelp ();
  372.             goto checkagain;
  373.         case '!':
  374.             {
  375.                 char buf[200];
  376.                 move (18, 0);
  377.                 putchar ('!');
  378.                 if (getline (buf) == NULL) {
  379.                     putchar (7);
  380.                     erase ();
  381.                     goto checkagain;
  382.                 }
  383.                 printf ("\r\n");
  384.                 shellescape (buf);
  385.                 erase ();
  386.                 goto checkagain;
  387.             }
  388.         case 'r': case 'R':
  389.             move (18, 0);
  390.             printf ("Replace with: ");
  391.             if (getline (token) == NULL) {
  392.                 putchar (7);
  393.                 erase ();
  394.                 goto checkagain;
  395.             }
  396.             inserttoken (secondbuf, begintoken, token, currentchar);
  397.             erase ();
  398.             goto checkagain;
  399.         case '0': case '1': case '2': case '3': case '4':
  400.         case '5': case '6': case '7': case '8': case '9':
  401.             if (possibilities[c - '0'][0] != 0) {
  402.                 strcpy (token, possibilities[c - '0']);
  403.                 inserttoken (secondbuf, begintoken, token, currentchar);                erase ();
  404.                 return;
  405.             }
  406.             putchar (7);
  407.             break;
  408.         case 'q': case 'Q':
  409.             quit = 1;
  410.             erase ();
  411.             return;
  412.         default:
  413.             putchar (7);
  414.             break;
  415.         }
  416.     }
  417. }
  418.  
  419. inserttoken (buf, start, token, currentchar)
  420. char *buf, *start, *token;
  421. char **currentchar;
  422. {
  423.     char copy[BUFSIZ];
  424.     char *p, *q;
  425.  
  426.     strcpy (copy, buf);
  427.  
  428.     for (p = buf, q = copy; p != start; p++, q++)
  429.         *p = *q;
  430.     while (*token)
  431.         *p++ = *token++;
  432.     q += *currentchar - start;
  433.     *currentchar = p;
  434.     while (*p++ = *q++)
  435.         ;
  436. }
  437.  
  438.  
  439. makepossibilities (word)
  440. char word[];
  441. {
  442.     int i;
  443.  
  444.     for (i = 0; i < 10; i++)
  445.         possibilities[i][0] = 0;
  446.     pcount = 0;
  447.  
  448.     if (pcount < 10) wrongletter (word);
  449.     if (pcount < 10) extraletter (word);
  450.     if (pcount < 10) missingletter (word);
  451.     if (pcount < 10) transposedletter (word);
  452.  
  453. }
  454.  
  455. char *cap();
  456.  
  457. insert (word)
  458. char *word;
  459. {
  460.     int i;
  461.  
  462.     for (i = 0; i < pcount; i++)
  463.         if (strcmp (possibilities[i], word) == 0)
  464.             return (0);
  465.  
  466.     strcpy (possibilities[pcount++], word);
  467.     if (pcount >= 10)
  468.         return (-1);
  469.     else
  470.         return (0);
  471. }
  472.  
  473. wrongletter (word)
  474. char word[];
  475. {
  476.     int i, c, n;
  477.     char newword[BUFSIZ];
  478.  
  479.     n = strlen (word);
  480.     strcpy (newword, word);
  481.  
  482.     for (i = 0; i < n; i++) {
  483.         for (newword[i] = 'A'; newword[i] <= 'Z'; newword[i]++) {
  484.             if (good (newword)) {
  485.                 if (insert (cap (newword, word)) < 0)
  486.                     return;
  487.             }
  488.         }
  489.         newword[i] = word[i];
  490.     }
  491. }
  492.  
  493. extraletter (word)
  494. char word[];
  495. {
  496.     char newword[BUFSIZ], *p, *s, *t;
  497.  
  498.     if (strlen (word) < 3)
  499.         return;
  500.  
  501.     for (p = word; *p; p++) {
  502.         for (s = word, t = newword; *s; s++)
  503.             if (s != p)
  504.                 *t++ = *s;
  505.         *t = 0;
  506.         if (good (newword)) {
  507.             if (insert (cap (newword, word)) < 0)
  508.                 return;
  509.         }
  510.     }
  511. }
  512.  
  513. missingletter (word)
  514. char word[];
  515. {
  516.     char newword[BUFSIZ], *p, *r, *s, *t;
  517.  
  518.     for (p = word; p == word || p[-1]; p++) {
  519.         for (s = newword, t = word; t != p; s++, t++)
  520.             *s = *t;
  521.         r = s++;
  522.         while (*t)
  523.             *s++ = *t++;
  524.         *s = 0;
  525.         for (*r = 'A'; *r <= 'Z'; (*r)++) {
  526.             if (good (newword)) {
  527.                 if (insert (cap (newword, word)) < 0)
  528.                     return;
  529.             }
  530.         }
  531.     }
  532. }
  533.  
  534. transposedletter (word)
  535. char word[];
  536. {
  537.     char newword[BUFSIZ];
  538.     int t;
  539.     char *p;
  540.  
  541.     strcpy (newword, word);
  542.     for (p = newword; p[1]; p++) {
  543.         t = p[0];
  544.         p[0] = p[1];
  545.         p[1] = t;
  546.         if (good (newword)) {
  547.             if (insert (cap (newword, word)) < 0)
  548.                 return;
  549.         }
  550.         t = p[0];
  551.         p[0] = p[1];
  552.         p[1] = t;
  553.     }
  554. }
  555.  
  556. char *
  557. cap (word, pattern)
  558. char word[], pattern[];
  559. {
  560.     static char newword[BUFSIZ];
  561.     char *p, *q;
  562.  
  563.     if (*word == 0)
  564.         return;
  565.  
  566.     if (isupper (pattern[0])) {
  567.         if (isupper (pattern[1])) {
  568.             for (p = word, q = newword; *p; p++, q++) {
  569.                 if (islower (*p))
  570.                     *q = toupper (*p);
  571.                 else
  572.                     *q = *p;
  573.             }
  574.             *q = 0;
  575.         } else {
  576.             if (islower (word [0]))
  577.                 newword[0] = toupper (word[0]);
  578.             else
  579.                 newword[0] = word[0];
  580.  
  581.             for (p = word + 1, q = newword + 1; *p; p++, q++)
  582.                 if (isupper (*p))
  583.                     *q = tolower (*p);
  584.                 else
  585.                     *q = *p;
  586.  
  587.             *q = 0;
  588.         }
  589.     } else {
  590.         for (p = word, q = newword; *p; p++, q++)
  591.             if (isupper (*p))
  592.                 *q = tolower (*p);
  593.             else
  594.                 *q = *p;
  595.         *q = 0;
  596.     }
  597.     return (newword);
  598. }
  599.  
  600. char *
  601. getline (s)
  602. char *s;
  603. {
  604.     char *p;
  605.     int c;
  606.  
  607.     p = s;
  608.  
  609.     while (1) {
  610.         c = (getchar () & NOPARITY);
  611.         if (c == '\\') {
  612.             putchar ('\\');
  613.             c = (getchar () & NOPARITY);
  614.             backup ();
  615.             putchar (c);
  616.             *p++ = c;
  617.         } else if (c == ('G' & 037)) {
  618.             return (NULL);
  619.         } else if (c == '\n' || c == '\r') {
  620.             *p = 0;
  621.             return (s);
  622.         } else if (c == erasechar) {
  623.             if (p != s) {
  624.                 p--;
  625.                 backup ();
  626.                 putchar (' ');
  627.                 backup ();
  628.             }
  629.         } else if (c == killchar) {
  630.             while (p != s) {
  631.                 p--;
  632.                 backup ();
  633.                 putchar (' ');
  634.                 backup ();
  635.             }
  636.         } else {
  637.             *p++ = c;
  638.             putchar (c);
  639.         }
  640.     }
  641. }
  642.  
  643. askmode ()
  644. {
  645.     char buf[BUFSIZ];
  646.     int i;
  647.  
  648.     if (fflag) {
  649.         if (freopen (askfilename, "w", stdout) == NULL) {
  650.             fprintf (stderr, "Can't create %s\n", askfilename);
  651.             exit (1);
  652.         }
  653.     }
  654.  
  655.     setbuf (stdin, NULL);
  656.     setbuf (stdout, NULL);
  657.  
  658.     while (gets (buf) != NULL) {
  659.         /* *line is like `i', @line is like `a' */
  660.         if (buf[0] == '*' || buf[0] == '@') {
  661.             treeinsert(buf + 1, buf[0] == '*');
  662.             printf("*\n");
  663.             treeoutput ();
  664.         } else if (good (buf)) {
  665.             if (rootword[0] == 0) {
  666.                 printf ("*\n");    /* perfect match */
  667.             } else {
  668.                 printf ("+ %s\n", rootword);
  669.             }
  670.         } else {
  671.             makepossibilities (buf);
  672.             if (possibilities[0][0]) {
  673.                 printf ("& ");
  674.                 for (i = 0; i < 10; i++) {
  675.                     if (possibilities[i][0] == 0)
  676.                         break;
  677.                     printf ("%s ", possibilities[i]);
  678.                 }
  679.                 printf ("\n");
  680.             } else {
  681.                 printf ("#\n");
  682.             }
  683.         }
  684.         if (sflag) {
  685.             stop ();
  686.             if (fflag) {
  687.                 rewind (stdout);
  688.                 creat (askfilename, 0666);
  689.             }
  690.         }
  691.     }
  692. }
  693.  
  694.  
  695. copyout(cc, cnt)
  696. char    **cc;
  697. {
  698.     while (--cnt >= 0) {
  699.         if (*(*cc) == 0)
  700.             break;
  701.         if (!lflag)
  702.             putc (*(*cc), outfile);
  703.         (*cc)++;
  704.     }
  705.  
  706. }
  707.